package com.shopping.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shopping.dto.MessageDTO;
import com.shopping.dto.MessageQueryDTO;
import com.shopping.entity.Message;
import com.shopping.entity.User;
import com.shopping.mapper.MessageMapper;
import com.shopping.mapper.UserMapper;
import com.shopping.service.MessageService;
import com.shopping.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    @Resource
    private UserService userService;

    @Resource
    private UserMapper userMapper;

    @Override
    @Transactional
    public boolean publishMessage(Message message) {
        try {
            if (message == null) {
                throw new IllegalArgumentException("留言内容不能为空");
            }
            if (message.getUserId() == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }
            if (StringUtils.isBlank(message.getContent())) {
                throw new IllegalArgumentException("留言内容不能为空");
            }

            message.setCreateTime(LocalDateTime.now());
            message.setIsReplied(false);
            message.setReply(null);
            message.setReplyTime(null);

            return save(message);
        } catch (Exception e) {
            log.error("发布留言失败", e);
            throw new RuntimeException("发布留言失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean replyMessage(Long messageId, String reply) {
        try {
            if (messageId == null) {
                throw new IllegalArgumentException("留言ID不能为空");
            }
            if (StringUtils.isBlank(reply)) {
                throw new IllegalArgumentException("回复内容不能为空");
            }

            Message message = getById(messageId);
            if (message == null) {
                throw new IllegalArgumentException("留言不存在");
            }

            message.setIsReplied(true);
            message.setReply(reply);
            message.setReplyTime(LocalDateTime.now());

            return updateById(message);
        } catch (Exception e) {
            log.error("回复留言失败", e);
            throw new RuntimeException("回复留言失败: " + e.getMessage());
        }
    }

    @Override
    public List<Message> getAllMessages() {
        try {
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
            wrapper.orderByDesc(Message::getCreateTime);
            List<Message> messages = list(wrapper);

            // 关联用户信息
            if (messages != null && !messages.isEmpty()) {
                List<Long> userIds = messages.stream()
                        .map(Message::getUserId)
                        .filter(id -> id != null)
                        .distinct()
                        .collect(Collectors.toList());

                if (!userIds.isEmpty()) {
                    Map<Long, User> userMap = userMapper.selectBatchIds(userIds)
                            .stream()
                            .collect(Collectors.toMap(User::getId, user -> user, (u1, u2) -> u1));

                    messages.forEach(message -> {
                        if (message.getUserId() != null) {
                            User user = userMap.get(message.getUserId());
                            if (user != null) {
                                message.setUser(user);
                                if (message.getUsername() == null) {
                                    message.setUsername(user.getUsername());
                                }
                            }
                        }
                    });
                }
            }

            return messages;
        } catch (Exception e) {
            log.error("获取留言列表失败", e);
            throw new RuntimeException("获取留言列表失败: " + e.getMessage());
        }
    }

    @Override
    public List<Message> getUserMessages(Long userId) {
        try {
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Message::getUserId, userId)
                    .orderByDesc(Message::getCreateTime);
            return list(wrapper);
        } catch (Exception e) {
            log.error("获取用户留言失败", e);
            throw new RuntimeException("获取用户留言失败: " + e.getMessage());
        }
    }

    @Override
    public Page<Message> getMessageListForAdmin(Integer page, Integer size, String username, String status) {
        try {
            Page<Message> pageParam = new Page<>(page, size);
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();

            if (StringUtils.isNotBlank(username)) {
                wrapper.like(Message::getUsername, username);
            }

            if (StringUtils.isNotBlank(status)) {
                wrapper.eq(Message::getIsReplied, "已回复".equals(status));
            }

            wrapper.orderByDesc(Message::getCreateTime);
            return page(pageParam, wrapper);
        } catch (Exception e) {
            log.error("获取管理员留言列表失败", e);
            throw new RuntimeException("获取管理员留言列表失败: " + e.getMessage());
        }
    }

    @Override
    public List<Message> getLatestMessages(Integer limit) {
        try {
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
            wrapper.orderByDesc(Message::getCreateTime)
                    .last("LIMIT " + limit);
            return list(wrapper);
        } catch (Exception e) {
            log.error("获取最新留言失败", e);
            throw new RuntimeException("获取最新留言失败: " + e.getMessage());
        }
    }

    @Override
    public Object getMessageStatistics() {
        try {
            // 统计总留言数
            long totalMessages = count();

            // 统计已回复和未回复留言数
            long repliedMessages = count(new LambdaQueryWrapper<Message>()
                    .eq(Message::getIsReplied, true));
            long unrepliedMessages = totalMessages - repliedMessages;

            // 统计今日新增留言数
            LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
            long newMessages = count(new LambdaQueryWrapper<Message>()
                    .ge(Message::getCreateTime, startOfDay));

            // 创建统计结果Map
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("totalMessages", totalMessages);
            statistics.put("repliedMessages", repliedMessages);
            statistics.put("unrepliedMessages", unrepliedMessages);
            statistics.put("newMessages", newMessages);

            return statistics;
        } catch (Exception e) {
            log.error("获取留言统计信息失败", e);
            throw new RuntimeException("获取留言统计信息失败: " + e.getMessage());
        }
    }

    @Override
    public Page<MessageDTO> getMessageList(MessageQueryDTO queryDTO) {
        try {
            Page<Message> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();

            if (StringUtils.isNotBlank(queryDTO.getUsername())) {
                wrapper.like(Message::getUsername, queryDTO.getUsername());
            }
            if (queryDTO.getIsReplied() != null) {
                wrapper.eq(Message::getIsReplied, queryDTO.getIsReplied());
            }

            wrapper.orderByDesc(Message::getCreateTime);
            Page<Message> messagePage = page(page, wrapper);

            Page<MessageDTO> dtoPage = new Page<>();
            dtoPage.setRecords(messagePage.getRecords().stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList()));
            dtoPage.setTotal(messagePage.getTotal());
            dtoPage.setCurrent(messagePage.getCurrent());
            dtoPage.setSize(messagePage.getSize());

            return dtoPage;
        } catch (Exception e) {
            log.error("获取留言列表失败", e);
            throw new RuntimeException("获取留言列表失败: " + e.getMessage());
        }
    }

    @Override
    public MessageDTO getMessageById(Long id) {
        try {
            Message message = getById(id);
            if (message == null) {
                throw new IllegalArgumentException("留言不存在");
            }
            return convertToDTO(message);
        } catch (Exception e) {
            log.error("获取留言详情失败", e);
            throw new RuntimeException("获取留言详情失败: " + e.getMessage());
        }
    }

    @Override
    public MessageDTO createMessage(Message message) {
        try {
            if (publishMessage(message)) {
                return convertToDTO(message);
            }
            throw new RuntimeException("创建留言失败");
        } catch (Exception e) {
            log.error("创建留言失败", e);
            throw new RuntimeException("创建留言失败: " + e.getMessage());
        }
    }

    @Override
    public MessageDTO updateMessage(Long id, Message message) {
        try {
            Message existingMessage = getById(id);
            if (existingMessage == null) {
                throw new IllegalArgumentException("留言不存在");
            }

            message.setId(id);
            message.setUserId(existingMessage.getUserId());
            message.setUsername(existingMessage.getUsername());
            message.setCreateTime(existingMessage.getCreateTime());
            message.setIsReplied(existingMessage.getIsReplied());
            message.setReply(existingMessage.getReply());
            message.setReplyTime(existingMessage.getReplyTime());
            message.setUpdateTime(LocalDateTime.now());

            if (updateById(message)) {
                return convertToDTO(message);
            }
            throw new RuntimeException("更新留言失败");
        } catch (Exception e) {
            log.error("更新留言失败", e);
            throw new RuntimeException("更新留言失败: " + e.getMessage());
        }
    }

    @Override
    public void deleteMessage(Long id) {
        try {
            if (id == null) {
                throw new IllegalArgumentException("留言ID不能为空");
            }

            Message message = getById(id);
            if (message == null) {
                throw new IllegalArgumentException("留言不存在");
            }

            if (!super.removeById(id)) {
                throw new RuntimeException("删除留言失败");
            }
        } catch (Exception e) {
            log.error("删除留言失败", e);
            throw new RuntimeException("删除留言失败: " + e.getMessage());
        }
    }

    @Override
    public void toggleMessageStatus(Long id) {
        try {
            Message message = getById(id);
            if (message == null) {
                throw new IllegalArgumentException("留言不存在");
            }

            message.setIsReplied(!message.getIsReplied());
            if (!updateById(message)) {
                throw new RuntimeException("更新留言状态失败");
            }
        } catch (Exception e) {
            log.error("更新留言状态失败", e);
            throw new RuntimeException("更新留言状态失败: " + e.getMessage());
        }
    }

    private MessageDTO convertToDTO(Message message) {
        MessageDTO dto = new MessageDTO();
        dto.setId(message.getId());
        dto.setUserId(message.getUserId());
        dto.setUsername(message.getUsername());
        dto.setContent(message.getContent());
        dto.setReply(message.getReply());
        dto.setIsReplied(message.getIsReplied());
        dto.setCreateTime(message.getCreateTime());
        dto.setReplyTime(message.getReplyTime());
        dto.setUpdateTime(message.getUpdateTime());
        dto.setUser(message.getUser());
        return dto;
    }
}